#define CATCH_CONFIG_MAIN

#include "catch.hpp"

#include "RECONR.hpp"

#include "RECONR/details/printV.hpp"
#include "RECONR/details/checkRanges.hpp"
#include "RECONR/details/simpleENDFTestString.hpp"


using namespace njoy;

static double nextafter( const double value ){
  return std::nextafter( value, std::numeric_limits< double >::infinity() );
}

std::string specialCaseString(){
  return
    " 1.001000+3 9.991673-1          0          0          1          0 125 2151    1\n"
    " 1.001000+3 1.000000+0          0          0          1          0 125 2151    2\n"
    " 1.000000-5 1.000000+5          0          0          0          0 125 2151    3\n"
    " 5.000000-1 1.276553+0          0          0          0          0 125 2151    4\n"
    " 0.000000+0 0.000000+0          0          0          0          0 125 2  099999\n";
}

std::string caseAString(){
  return
    " 5.614000+4 1.387080+2          0          0          1          05655 2151     \n"
    " 5.614000+4 1.000000+0          0          0          1          05655 2151     \n"
    // base
    " 2.300000+4 1.000000+5          2          1          0          05655 2151     \n"
    // range CONT
    " 0.000000+0 6.233000-1          0          0          3          05655 2151     \n"
    // L=0 LIST                                                                      
    " 1.387090+2 0.000000+0          0          0          6          15655 2151     \n"
    " 4.400000+3 5.000000-1 1.000000+0 4.400000-1 5.000000-2 0.000000+05655 2151     \n"
    // L=1 LIST                                                                      
    " 1.387090+2 0.000000+0          1          0         12          25655 2151     \n"
    " 4.400000+3 5.000000-1 1.000000+0 5.280000-1 9.000000-2 0.000000+05655 2151     \n"
    " 2.200000+3 1.500000+0 1.000000+0 2.640000-1 9.000000-2 0.000000+05655 2151     \n"
    // L=2 LIST                                                                      
    " 1.387090+2 0.000000+0          2          0         12          25655 2151     \n"
    " 2.200000+3 1.500000+0 1.000000+0 3.300000-2 5.000000-2 0.000000+05655 2151     \n"
    " 1.466670+3 2.500000+0 1.000000+0 2.200000-2 5.000000-2 0.000000+05655 2151     \n"
    " 0.000000+0 0.000000+0          0          0          0          05655 2  099999\n";
}

std::string caseBString(){
  return 
    " 9.424000+4 2.379920+2          0          0          1          09440 2151     \n"
    " 9.424000+4 1.000000+0          0          1          1          09440 2151     \n"
    " 5.700000+3 4.000000+4          2          1          0          09440 2151     \n"
    // LIST
    " 0.000000+0 8.880000-1          0          0         14          39440 2151     \n"
    " 5.700000+3 7.000000+3 8.000000+3 9.000000+3 1.000000+4 1.200000+49440 2151     \n"
    " 1.400000+4 1.600000+4 1.800000+4 2.000000+4 2.500000+4 3.000000+49440 2151     \n"
    " 3.500000+4 4.000000+4                                            9440 2151     \n"
    // L=0 CONT                                                                      
    " 2.379920+2 0.000000+0          0          0          1          09440 2151     \n"
    // L=0 LIST                                                                      
    " 0.000000+0 0.000000+0          0          1         20          09440 2151     \n"
    " 1.310000+1 5.000000-1 1.000000+0 1.572000-3 3.100000-2 0.000000+09440 2151     \n"
    " 1.256000-3 1.544000-3 1.825000-3 2.025000-3 2.119000-3 2.051000-39440 2151     \n"
    " 1.992000-3 1.879000-3 1.860000-3 1.838000-3 1.694000-3 1.581000-39440 2151     \n"
    " 1.481000-3 1.403000-3                                            9440 2151     \n"
    // L=1 CONT                                                                      
    " 2.379920+2 0.000000+0          1          0          2          09440 2151     \n"
    // L=1,J=0 LIST                                                                  
    " 0.000000+0 0.000000+0          1          1         20          09440 2151     \n"
    " 1.310000+1 5.000000-1 1.000000+0 3.013000-3 3.100000-2 0.000000+09440 2151     \n"
    " 4.314000-3 4.572000-3 4.740000-3 5.000000-3 5.520000-3 7.057000-39440 2151     \n"
    " 8.251000-3 9.276000-3 9.930000-3 1.035000-2 1.210000-2 1.341000-29440 2151     \n"
    " 1.456000-2 1.542000-2                                            9440 2151     \n"
    // L=1,J=1 LIST                                                                  
    " 0.000000+0 0.000000+0          1          2         20          09440 2151     \n"
    " 6.697000+0 1.500000+0 1.000000+0 1.540000-3 3.100000-2 0.000000+09440 2151     \n"
    " 1.207000-3 1.299000-3 1.326000-3 1.397000-3 1.544000-3 1.973000-39440 2151     \n"
    " 2.317000-3 2.581000-3 2.811000-3 3.075000-3 3.494000-3 3.887000-39440 2151     \n"
    " 4.290000-3 4.586000-3                                            9440 2151     \n"
    // L=2 CONT                                                                      
    " 2.379920+2 0.000000+0          2          0          2          09440 2151     \n"
    // L=2,J=0 LIST                                                                  
    " 0.000000+0 0.000000+0          2          1         20          09440 2151     \n"
    " 6.697000+0 1.500000+0 1.000000+0 8.304300-4 3.100000-2 0.000000+09440 2151     \n"
    " 1.000000-9 1.000000-9 1.000000-9 1.000000-9 1.000000-9 1.000000-99440 2151     \n"
    " 1.000000-9 1.000000-9 1.000000-9 1.000000-9 1.000000-9 1.000000-99440 2151     \n"
    " 1.000000-9 1.000000-9                                            9440 2151     \n"
    // L=2,J=1 LIST                                                                  
    " 0.000000+0 0.000000+0          2          2         20          09440 2151     \n"
    " 4.633000+0 2.500000+0 1.000000+0 5.744900-4 3.100000-2 0.000000+09440 2151     \n"
    " 1.000000-9 1.000000-9 1.000000-9 1.000000-9 1.000000-9 1.000000-99440 2151     \n"
    " 1.000000-9 1.000000-9 1.000000-9 1.000000-9 1.000000-9 1.000000-99440 2151     \n"
    " 1.000000-9 1.000000-9                                            9440 2151     \n"
    " 0.000000+0 0.000000+0          0          0          0          09440 2  099999\n";
}

std::string caseCString(){
  return
    // Isotope                                           NIS
    " 3.809000+4 8.913540+1          0          0          1          03843 2151     \n"
    //                                        LFW        NER
    " 3.809000+4 1.000000+0          0          1          1          03843 2151     \n"
    // base                        LRU        LRF
    " 6.000000+3 1.000000+5          2          2          0          03843 2151     \n"
    // range CONT                 LSSF                   NLS
    " 0.000000+0 6.795900-1          0          0          3          03843 2151     \n"
    // L=0 CONT                                          NJS
    " 8.913540+1 0.000000+0          0          0          1          03843 2151     \n"
    // L=0 LIST                                                                      
    " 5.000000-1 0.000000+0          5          0         84         133843 2151     \n"
    " 0.000000+0 0.000000+0 1.000000+0 2.000000+0 3.000000+0 4.000000+03843 2151     \n"
    " 6.000000+3 1.240600+4 0.000000+0 4.590100-1 2.050000-1 0.000000+03843 2151     \n"
    " 7.000000+3 1.240600+4 0.000000+0 4.590100-1 2.050000-1 0.000000+03843 2151     \n"
    " 8.000000+3 1.240600+4 0.000000+0 4.590100-1 2.050000-1 0.000000+03843 2151     \n"
    " 1.000000+4 1.231300+4 0.000000+0 4.555800-1 2.050000-1 0.000000+03843 2151     \n"
    " 1.500000+4 1.226300+4 0.000000+0 4.537400-1 2.050000-1 0.000000+03843 2151     \n"
    " 2.500000+4 1.212200+4 0.000000+0 4.485000-1 2.050000-1 0.000000+03843 2151     \n"
    " 3.000000+4 1.205400+4 0.000000+0 4.460100-1 2.050000-1 0.000000+03843 2151     \n"
    " 4.000000+4 1.191800+4 0.000000+0 4.409700-1 2.050000-1 0.000000+03843 2151     \n"
    " 5.000000+4 1.181000+4 0.000000+0 4.369800-1 2.050000-1 0.000000+03843 2151     \n"
    " 6.000000+4 1.113000+4 0.000000+0 4.118100-1 2.050000-1 0.000000+03843 2151     \n"
    " 7.000000+4 1.077400+4 0.000000+0 3.986200-1 2.050000-1 0.000000+03843 2151     \n"
    " 8.000000+4 1.039500+4 0.000000+0 3.846100-1 2.050000-1 0.000000+03843 2151     \n"
    " 1.000000+5 9.669700+3 0.000000+0 3.577800-1 2.050000-1 0.000000+03843 2151     \n"
    // L=1 CONT                                                                      
    " 8.913540+1 0.000000+0          1          0          2          03843 2151     \n"
    // L=1,J=0 LIST                                                                  
    " 5.000000-1 0.000000+0          5          0         84         133843 2151     \n"
    " 0.000000+0 0.000000+0 0.000000+0 1.000000+0 0.000000+0 0.000000+03843 2151     \n"
    " 6.000000+3 1.240600+4 0.000000+0 6.723800+0 2.050000-1 0.000000+03843 2151     \n"
    " 7.000000+3 1.240600+4 0.000000+0 6.723800+0 2.050000-1 0.000000+03843 2151     \n"
    " 8.000000+3 1.240600+4 0.000000+0 6.723800+0 2.050000-1 0.000000+03843 2151     \n"
    " 1.000000+4 1.231300+4 0.000000+0 6.673600+0 2.050000-1 0.000000+03843 2151     \n"
    " 1.500000+4 1.226300+4 0.000000+0 6.646600+0 2.050000-1 0.000000+03843 2151     \n"
    " 2.500000+4 1.212200+4 0.000000+0 6.569900+0 2.050000-1 0.000000+03843 2151     \n"
    " 3.000000+4 1.205400+4 0.000000+0 6.533500+0 2.050000-1 0.000000+03843 2151     \n"
    " 4.000000+4 1.191800+4 0.000000+0 6.459600+0 2.050000-1 0.000000+03843 2151     \n"
    " 5.000000+4 1.181000+4 0.000000+0 6.401200+0 2.050000-1 0.000000+03843 2151     \n"
    " 6.000000+4 1.113000+4 0.000000+0 6.032400+0 2.050000-1 0.000000+03843 2151     \n"
    " 7.000000+4 1.077400+4 0.000000+0 5.839300+0 2.050000-1 0.000000+03843 2151     \n"
    " 8.000000+4 1.039500+4 0.000000+0 5.634100+0 2.050000-1 0.000000+03843 2151     \n"
    " 1.000000+5 9.669700+3 0.000000+0 5.241000+0 2.050000-1 0.000000+03843 2151     \n"
    // L=1,J=1 LIST                                                                  
    " 1.500000+0 0.000000+0          5          0         84         133843 2151     \n"
    " 0.000000+0 0.000000+0 0.000000+0 1.000000+0 0.000000+0 0.000000+03843 2151     \n"
    " 6.000000+3 6.202800+3 0.000000+0 3.361900+0 2.050000-1 0.000000+03843 2151     \n"
    " 7.000000+3 6.202800+3 0.000000+0 3.361900+0 2.050000-1 0.000000+03843 2151     \n"
    " 8.000000+3 6.202800+3 0.000000+0 3.361900+0 2.050000-1 0.000000+03843 2151     \n"
    " 1.000000+4 6.156500+3 0.000000+0 3.336800+0 2.050000-1 0.000000+03843 2151     \n"
    " 1.500000+4 6.131600+3 0.000000+0 3.323300+0 2.050000-1 0.000000+03843 2151     \n"
    " 2.500000+4 6.060800+3 0.000000+0 3.285000+0 2.050000-1 0.000000+03843 2151     \n"
    " 3.000000+4 6.027200+3 0.000000+0 3.266800+0 2.050000-1 0.000000+03843 2151     \n"
    " 4.000000+4 5.959100+3 0.000000+0 3.229800+0 2.050000-1 0.000000+03843 2151     \n"
    " 5.000000+4 5.905100+3 0.000000+0 3.200600+0 2.050000-1 0.000000+03843 2151     \n"
    " 6.000000+4 5.564900+3 0.000000+0 3.016200+0 2.050000-1 0.000000+03843 2151     \n"
    " 7.000000+4 5.386800+3 0.000000+0 2.919600+0 2.050000-1 0.000000+03843 2151     \n"
    " 8.000000+4 5.197500+3 0.000000+0 2.817000+0 2.050000-1 0.000000+03843 2151     \n"
    " 1.000000+5 4.834900+3 0.000000+0 2.620500+0 2.050000-1 0.000000+03843 2151     \n"
    // L=2 CONT                                                                      
    " 8.913540+1 0.000000+0          2          0          2          03843 2151     \n"
    // L=2,J=0 LIST                                                                  
    " 1.500000+0 0.000000+0          5          0         84         133843 2151     \n"
    " 0.000000+0 0.000000+0 0.000000+0 1.000000+0 0.000000+0 0.000000+03843 2151     \n"
    " 6.000000+3 6.202800+3 0.000000+0 2.233000-1 2.050000-1 0.000000+03843 2151     \n"
    " 7.000000+3 6.202800+3 0.000000+0 2.233000-1 2.050000-1 0.000000+03843 2151     \n"
    " 8.000000+3 6.202800+3 0.000000+0 2.233000-1 2.050000-1 0.000000+03843 2151     \n"
    " 1.000000+4 6.156500+3 0.000000+0 2.216300-1 2.050000-1 0.000000+03843 2151     \n"
    " 1.500000+4 6.131600+3 0.000000+0 2.207400-1 2.050000-1 0.000000+03843 2151     \n"
    " 2.500000+4 6.060800+3 0.000000+0 2.181900-1 2.050000-1 0.000000+03843 2151     \n"
    " 3.000000+4 6.027200+3 0.000000+0 2.169800-1 2.050000-1 0.000000+03843 2151     \n"
    " 4.000000+4 5.959100+3 0.000000+0 2.145300-1 2.050000-1 0.000000+03843 2151     \n"
    " 5.000000+4 5.905100+3 0.000000+0 2.125900-1 2.050000-1 0.000000+03843 2151     \n"
    " 6.000000+4 5.564900+3 0.000000+0 2.003400-1 2.050000-1 0.000000+03843 2151     \n"
    " 7.000000+4 5.386800+3 0.000000+0 1.939200-1 2.050000-1 0.000000+03843 2151     \n"
    " 8.000000+4 5.197500+3 0.000000+0 1.871100-1 2.050000-1 0.000000+03843 2151     \n"
    " 1.000000+5 4.834900+3 0.000000+0 1.740500-1 2.050000-1 0.000000+03843 2151     \n"
    // L=2,J=1 LIST                                                                  
    " 2.500000+0 0.000000+0          5          0         84         133843 2151     \n"
    " 0.000000+0 0.000000+0 0.000000+0 1.000000+0 0.000000+0 0.000000+03843 2151     \n"
    " 6.000000+3 4.135200+3 0.000000+0 1.488700-1 2.050000-1 0.000000+03843 2151     \n"
    " 7.000000+3 4.135200+3 0.000000+0 1.488700-1 2.050000-1 0.000000+03843 2151     \n"
    " 8.000000+3 4.135200+3 0.000000+0 1.488700-1 2.050000-1 0.000000+03843 2151     \n"
    " 1.000000+4 4.104300+3 0.000000+0 1.477600-1 2.050000-1 0.000000+03843 2151     \n"
    " 1.500000+4 4.087700+3 0.000000+0 1.471600-1 2.050000-1 0.000000+03843 2151     \n"
    " 2.500000+4 4.040500+3 0.000000+0 1.454600-1 2.050000-1 0.000000+03843 2151     \n"
    " 3.000000+4 4.018100+3 0.000000+0 1.446500-1 2.050000-1 0.000000+03843 2151     \n"
    " 4.000000+4 3.972700+3 0.000000+0 1.430200-1 2.050000-1 0.000000+03843 2151     \n"
    " 5.000000+4 3.936800+3 0.000000+0 1.417200-1 2.050000-1 0.000000+03843 2151     \n"
    " 6.000000+4 3.710000+3 0.000000+0 1.335600-1 2.050000-1 0.000000+03843 2151     \n"
    " 7.000000+4 3.591200+3 0.000000+0 1.292800-1 2.050000-1 0.000000+03843 2151     \n"
    " 8.000000+4 3.465000+3 0.000000+0 1.247400-1 2.050000-1 0.000000+03843 2151     \n"
    " 1.000000+5 3.223200+3 0.000000+0 1.160400-1 2.050000-1 0.000000+03843 2151     \n"
    " 0.000000+0 0.000000+0          0          0          0          03843 2  099999\n";
}                                                                                  

RP::Isotope isotope(){

  auto material = details::ENDFMaterial( "SLBW" );
  auto MT151 = material.file( 2 ).section( 151 ).parse< 2, 151 >();

  return MT151.isotopes().front();
}

RP::SLBW breitWigner(){

  auto material = details::ENDFMaterial( "SLBW" );
  auto MT151 = material.file( 2 ).section( 151 ).parse< 2, 151 >();

  return std::get< RP::SLBW >(
      MT151.isotopes().front().resonanceRanges().front().parameters() );
}

RP::ResonanceRange reichMoore(){

  auto material = details::ENDFMaterial( "RM" );
  auto MT151 = material.file( 2 ).section( 151 ).parse< 2, 151 >();

  return MT151.isotopes().front().resonanceRanges().front();
}

RP::ResonanceRange rMatrixLimited(){

  auto material = details::ENDFMaterial( "RML" );
  auto MT151 = material.file( 2 ).section( 151 ).parse< 2, 151 >();

  return MT151.isotopes().front().resonanceRanges().front();
}

RP::ResonanceRange specialCase(){
  long ln = 0;

  auto scs = specialCaseString();
  auto begin = scs.begin();
  auto end = scs.end();

  njoy::ENDFtk::HeadRecord head{ begin, end, ln };
  njoy::ENDFtk::section::Type< 2, 151 > mt151{ head, begin, end, ln, 125 };

  return mt151.isotopes().front().resonanceRanges().front();
}

RP::ResonanceRange caseA(){
    long ln = 0;
    
    std::string ENDF = caseAString();
    auto begin = ENDF.begin();
    auto end = ENDF.end();

    njoy::ENDFtk::HeadRecord head{ begin, end, ln };
    njoy::ENDFtk::section::Type< 2, 151 > mt151{ head, begin, end, ln, 5655 };

    return mt151.isotopes().front().resonanceRanges().front();
}

RP::ResonanceRange caseB(){
    long ln = 0;

    std::string ENDF = caseBString();
    auto begin = ENDF.begin();
    auto end = ENDF.end();

    njoy::ENDFtk::HeadRecord head{ begin, end, ln };
    njoy::ENDFtk::section::Type< 2, 151 > mt151{ head, begin, end, ln, 9440 };

    return mt151.isotopes().front().resonanceRanges().front();
}

RP::ResonanceRange caseC(){
    long ln = 0;

    std::string ENDF = caseCString();
    auto begin = ENDF.begin();
    auto end = ENDF.end();

    njoy::ENDFtk::HeadRecord head{ begin, end, ln };
    njoy::ENDFtk::section::Type< 2, 151 > mt151{ head, begin, end, ln, 3843 };

    return mt151.isotopes().front().resonanceRanges().front();
}

#include "RECONR/ReferenceGrid/test/call.hpp"
